/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.user.service.impl;

import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.admin.api.feign.RemoteTokenService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.customize.enums.AbnormalEnum;
import com.pig4cloud.pigx.common.customize.enums.CommonDictEnum;
import com.pig4cloud.pigx.common.customize.exception.DuckweedException;
import com.pig4cloud.pigx.common.customize.i18n.util.MessageUtils;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.id.IdWorker;
import com.pig4cloud.pigx.common.customize.utils.id.UUID;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.user.api.feign.DuckweedRemoteGatewayService;
import com.pig4cloud.pigx.user.constant.FuelProfitConstant;
import com.pig4cloud.pigx.user.constant.PublicChainTypeEnums;
import com.pig4cloud.pigx.user.constant.RedisMessageType;
import com.pig4cloud.pigx.user.constant.WalletConstant;
import com.pig4cloud.pigx.user.dto.*;
import com.pig4cloud.pigx.user.entity.*;
import com.pig4cloud.pigx.user.enums.*;
import com.pig4cloud.pigx.user.mapper.UserMapper;
import com.pig4cloud.pigx.user.service.*;
import com.pig4cloud.pigx.user.util.TronVerifyMessage;
import com.pig4cloud.pigx.user.util.Web3jSignatureValid;
import com.pig4cloud.pigx.user.vo.*;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.stereotype.Service;
import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Keys;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.*;
import java.util.stream.Collectors;

import static com.pig4cloud.pigx.user.constant.I18nMessages.*;

/**
 * 用户 实现类
 *
 * @author pigx code generator
 * @date 2022-11-18 11:52:08
 */
@Service
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

	private final StringRedisTemplate stringRedisTemplate;

	private final IdWorker idWorker;

	private final MysqlUtil mysqlUtil;

	private final UserAddressService addressService;

	private final DuckweedRemoteGatewayService duckweedRemoteGatewayService;

	private final CurrencyService currencyService;

	private final CapitalAccountService capitalAccountService;

	private final FuelAccountService fuelAccountService;

	private final FuelConsumeService fuelConsumeService;

	private final FuelReceiveDividendsService fuelReceiveDividendsService;

	private final EmailService emailService;

	private final UserApiService userApiService;

	private final RemoteTokenService tokenService;
	@Override
	public R<List<Long>> getAdminUserList() {
		try {
			List<User> list = new User().selectList(new QueryWrapper<User>() {{
				select("id");
			}});
			List<Long> longs = list.stream().map(User::getId).collect(Collectors.toList());
			return R.ok(longs);
		} catch (Exception e) {
			return R.ok(new ArrayList<>());
		}
	}

	@Override
	public R<Page<AdminUserPageVO>> getAdminPage(AdminUserPageDTO dto) {
		try {
			Page<AdminUserPageVO> adminPage = baseMapper.selectAdminPage(new Page<User>() {{
				setCurrent(dto.getCurrent());
				setSize(dto.getSize());
			}}, dto);
			for (AdminUserPageVO user : adminPage.getRecords()) {
				user.setLevel(UserEnums.Level.findName(Integer.valueOf(user.getLevel())));
				user.setIsDisableLevel(CommonDictEnum.YesOrNo.findName(user.getIsDisableLevel()));
				if (user.getJQuantity() == null) {
					user.setJQuantity(BigDecimal.ZERO);
				}
				if (user.getZQuantity() == null) {
					user.setZQuantity(BigDecimal.ZERO);
				}
				if (user.getSQuantity() == null) {
					user.setSQuantity(BigDecimal.ZERO);
				}
				if (user.getPQuantity() == null) {
					user.setPQuantity(BigDecimal.ZERO);
				}
			}
			return R.ok(adminPage);
		} catch (DuckweedException ignored) {
			throw ignored;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public R<AdminUserTreeVO> adminGetUserDetail(Long id) {
		try {
			User user = baseMapper.selectById(id);
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			// 获取节点树形结构
			AdminUserTreeVO treeUser = new AdminUserTreeVO();
			BeanUtils.copyProperties(user,treeUser);
			treeUser.setLevel(UserEnums.Level.findName(user.getLevel()));
			treeUser.setIsDisableLevel(CommonDictEnum.YesOrNo.findName(treeUser.getIsDisableLevel()));
			getTreeChild(treeUser);
			return R.ok(treeUser);
		} catch (DuckweedException ignored) {
			throw ignored;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 邮箱注册并登录
	 * @param header header
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<AppUserVO> emailRegisteredAndLogin(HttpHeaders header, RegisteredUserDTO dto) {
		try {
			User user = new User();
			Long count = baseMapper.selectCount(new QueryWrapper<User>() {{
				eq("email", dto.getEmail());
			}});
			if (count > 0) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"该邮箱已被注册过");
			}
			// 校验验证码
			String key = dto.getEmail() + " massage = " + RedisMessageType.Customer_Registration;
			Boolean hasKey = stringRedisTemplate.hasKey(key);
			if (Boolean.FALSE.equals(hasKey)) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码已过期");
			}
			String s = stringRedisTemplate.opsForValue().get(key);
			if (s == null || !s.equals(dto.getVerificationCode())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码错误");
			}
			user.setId(idWorker.nextId());
			// 设置邮箱 用户名 资金密码
			user.setEmail(dto.getEmail());
			user.setUserName(dto.getUserName());
			user.setPassword(dto.getPassword());
			// 初始化等级状态等基础信息
			user.setLevel(UserEnums.Level.LEVEL_0.getValue());
			user.setIsActivation(CommonDictEnum.YesOrNo.NO.getValue());
			user.setIsDisableLevel(CommonDictEnum.YesOrNo.NO.getValue());
			// 随机uuid邀请码
			UUID id = UUID.randomUUID();
			String[] idd = id.toString().split("-");
			user.setInvitationCode(idd[0] + idd[1]);
			// 查询用户邀请码对应上级信息
			if (dto.getInvitationCode() != null && !dto.getInvitationCode().isEmpty()) {
				Long parent = updateParentByRegistered(dto.getInvitationCode());
				user.setParentId(parent);
			}
			// 注册
			try {
				mysqlUtil.startLocalTx();
				baseMapper.insert(user);
				// 新增USC地址
				addressService.insertByRegistered(user);
				// 新增资金账户
				capitalAccountService.createCapital(user);
				// 新增燃料账户
				fuelAccountService.createFuel(user);
				mysqlUtil.commitLocalTx();
				stringRedisTemplate.delete(key);
			} catch (Exception e) {
				mysqlUtil.rollbackLocalTx();
				throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
			}
			AppUserVO vo = new AppUserVO();
			BeanUtils.copyProperties(user,vo);
			// 登录生成token
			Map<String, Object> param = new HashMap<>(4);
			param.put("username", user.getEmail());
			param.put("password", user.getEmail());
			param.put("scope", "server");
			param.put("grant_type", "password");
			header.set(HttpHeaders.AUTHORIZATION, HttpUtil.buildBasicAuth("dapp", "dapp", StandardCharsets.UTF_8));
			Map<String, Object> map = duckweedRemoteGatewayService.sendGateWay(header, param, SecurityConstants.FROM_IN);
			if (map.containsKey("access_token")) {
				vo.setAccessToken(map.get("access_token").toString());
			}
			return R.ok(vo);
		} catch (DuckweedException ignored) {
			throw ignored;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 邮箱登录
	 * @param header header
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<AppUserVO> emailLogin(HttpHeaders header, EmailLoginDTO dto) {
		try {
			User user = baseMapper.selectOne(new QueryWrapper<User>() {{
				eq("email", dto.getEmail());
			}});
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
//			// 校验验证码
			/*String key = dto.getEmail() + " massage = " + RedisMessageType.Email_Login;
			Boolean hasKey = stringRedisTemplate.hasKey(key);
			if (Boolean.FALSE.equals(hasKey)) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码已过期");
			}
			String s = stringRedisTemplate.opsForValue().get(key);
			if (s == null || !s.equals(dto.getVerificationCode())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码错误");
			}*/
			AppUserVO vo = new AppUserVO();
			BeanUtils.copyProperties(user,vo);
			// 登录生成token
			Map<String, Object> param = new HashMap<>(4);
			param.put("username", user.getAddress());
			param.put("password", user.getAddress());
			param.put("scope", "server");
			param.put("grant_type", "password");
			header.set(HttpHeaders.AUTHORIZATION, HttpUtil.buildBasicAuth("dapp", "dapp", StandardCharsets.UTF_8));
			Map<String, Object> map = duckweedRemoteGatewayService.sendGateWay(header, param, SecurityConstants.FROM_IN);
			if (map.containsKey("access_token")) {
				vo.setAccessToken(map.get("access_token").toString());
			}
			// stringRedisTemplate.delete(key);
			return R.ok(vo);
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}

	}

	/**
	 * 地址登录
	 * @param header header
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R login(HttpHeaders header, UserMobileDTO dto) {
		User user = new User();
		BeanUtils.copyProperties(dto,user);
		if (user.getAddress() == null || user.getAddress().isEmpty() ||
				user.getSignature() == null || user.getSignature().isEmpty() ||
				user.getChain() == null || user.getChain().isEmpty()) {
			return R.failed(MessageUtils.get(REQUEST_PARAMETER_INVALID));
		}
		//获取加签客户massage，判断是否存在
		String addressMessage = stringRedisTemplate.opsForValue()
				.get(user.getAddress() + " massage = " + RedisMessageType.Customer_Address_Message);
		if (addressMessage == null || addressMessage.isEmpty()) {
			return R.failed(MessageUtils.get(USER_WALLET_ADDRESS_NOT_AUTHORIZED));
		}
		//判断用户登录公链
		if (user.getChain() != null && !user.getChain().isEmpty() &&
				user.getChain().toUpperCase().equals(UserEnums.Chain.ETH.getValue())) {
			//以太坊地址登录时
			//校验加密后密文
			boolean signatureValid = Web3jSignatureValid.isSignatureValid(
					user.getAddress(), user.getSignature(), addressMessage);
			//校验正确请求pigx-gatewey登录生成token返回
			if (!signatureValid) {
				return R.failed(MessageUtils.get(SIGNATURE_VERIFICATION_ERROR));
			}
		} else if (user.getChain() != null && !user.getChain().isEmpty() &&
				user.getChain().equals(PublicChainTypeEnums.TRX.getCode())) {
			//波场
			boolean verify = TronVerifyMessage.verify(addressMessage, user.getSignature(), user.getAddress());
			if (!verify) {
				return R.failed(MessageUtils.get(SIGNATURE_VERIFICATION_ERROR));
			}
		} else {
			return R.failed(MessageUtils.get(PLEASE_ENTER_THE_CORRECT_PUBLIC_CHAIN));
		}
		//根据地址查询用户
		User userInfo = this.getOne(new QueryWrapper<User>().eq("address", user.getAddress()));
		//保存用户地址
		if (userInfo == null) {
			//账户状态
			user.setLevel(UserEnums.Level.LEVEL_0.getValue());
			user.setIsActivation(CommonDictEnum.YesOrNo.NO.getValue());
			user.setIsDisableLevel(CommonDictEnum.YesOrNo.NO.getValue());
			//雪花id
			user.setId(idWorker.nextId());
			baseMapper.insert(user);
		}
		try {
			//请求oauth2登录接口
			Map<String, Object> param = new HashMap<>();
			param.put("username", user.getAddress());
			param.put("password", user.getAddress());
			param.put("scope", "server");
			param.put("grant_type", "password");
			AppUserVO appUserVO = new AppUserVO();
			//返回用户是否注册
			if (userInfo == null) {
				BeanUtils.copyProperties(user,appUserVO);
				appUserVO.setUserIsExist(false);
			} else {
				BeanUtils.copyProperties(userInfo,appUserVO);
				appUserVO.setUserIsExist(userInfo.getEmail() != null && !userInfo.getEmail().isEmpty());
			}
			header.set(HttpHeaders.AUTHORIZATION, HttpUtil.buildBasicAuth("dapp", "dapp", StandardCharsets.UTF_8));
			Map<String, Object> map = duckweedRemoteGatewayService.sendGateWay(header, param, SecurityConstants.FROM_IN);
			if (map.containsKey("access_token")) {
				appUserVO.setAccessToken(map.get("access_token").toString());
			}
			//删除缓存签名原文
			stringRedisTemplate.delete(user.getAddress() + " massage = " + RedisMessageType.Customer_Address_Message);
			return R.ok(appUserVO);
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 获取游客token
	 * @return token
	 */
	@Override
	public R<String> getTouristToken(HttpHeaders header) {
		try {
			List<String> authorization = header.get("Authorization");
			if (authorization != null && authorization.size() > 0  && !"Bearer".equals(authorization.get(0))) {
				String token = authorization.get(0);
				token = token.substring(7);
				R<Map<String, Object>> queryToken = tokenService.queryToken(token, SecurityConstants.FROM_IN);
				if (queryToken.getData() != null) {
					String userName = queryToken.getData().get("username").toString();
					Long count = baseMapper.selectCount(new QueryWrapper<User>() {{
						eq("address", userName);
					}});
					if (count != null && count > 0) {
						return R.ok("success");
					}
				} else {
					return R.ok(token(header));
				}
			}
		} catch (Exception e) {
			return R.ok(token(header));
		}
		return R.ok(token(header));
	}

	private String token(HttpHeaders header) {
		// 账户 (bsc)
		ECKeyPair ecKeyPair;
		try {
			ecKeyPair = Keys.createEcKeyPair();
		} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchProviderException e) {
			throw new RuntimeException(e);
		}
		// 公钥
		String bscPublicKey = ecKeyPair.getPublicKey().toString(16);
		// 地址
		String bscAddress = "0x" + Keys.getAddress(bscPublicKey);
		Map<String, Object> param = new HashMap<>(4);
		param.put("username", bscAddress);
		param.put("password", bscAddress);
		param.put("scope", "server");
		param.put("grant_type", "password");
		header.set(HttpHeaders.AUTHORIZATION, HttpUtil.buildBasicAuth("dapp", "dapp", StandardCharsets.UTF_8));
		try {
			Map<String, Object> map = duckweedRemoteGatewayService.sendGateWay(header, param, SecurityConstants.FROM_IN);
			if (map.containsKey("access_token")) {
				return map.get("access_token").toString();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "success";
	}

	/**
	 * 获取app端登录用户详情
	 * @return detail
	 */
	@Override
	public R<AppUserDetailVO> getAppUserDetail(Long id) {
		if (id == -1) {
			PigxUser user = SecurityUtil.getLoginUser();
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			id = user.getId();
		}
		try {
			User select = baseMapper.selectById(id);
			if (select == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			AppUserDetailVO vo = new AppUserDetailVO();
			BeanUtils.copyProperties(select,vo);
			// 字典项翻译
			vo.setLevel(UserEnums.Level.findName(select.getLevel()));
			vo.setIsActivation(CommonDictEnum.YesOrNo.findName(vo.getIsActivation()));
			vo.setIsDisableLevel(CommonDictEnum.YesOrNo.findName(vo.getIsDisableLevel()));
			// 查询用户API绑定信息
			List<UserApi> userApis = userApiService.list(new QueryWrapper<UserApi>() {{
				eq("user_id", select.getId());
				select("platform_id");
			}});
			// 返回用户绑定过的平台id
			if (userApis.size() > 0) {
				List<Long> collect = userApis.stream().map(UserApi::getPlatformId).collect(Collectors.toList());
				vo.setBindingPlatformList(collect);
			}
			// 查询用户是否签订合同
			Long finalId = id;
			long selectCount = new UserAgreement().selectCount(new QueryWrapper<UserAgreement>() {{
				eq("user_id", finalId);
			}});
			vo.setIsAgreement(selectCount > 0 ? 1 : 0);
			List<User> userList = new ArrayList<>();
			getAllChild(userList,vo.getId());
			List<Long> longs = userList.stream().map(User::getId).collect(Collectors.toList());
			longs.add(vo.getId());
			new TransferDetailed().selectOne(new QueryWrapper<TransferDetailed>(){{
				eq("type",TransferEnums.Type.TO_FUEL.getValue());
				select("sum(quantity)");
				in("user_id",longs);
			}});
			return R.ok(vo);
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 获取app用户余额
	 * @return r
	 */
	@Override
	public R<UserBalanceVO> getUserBalance() {
		try {
			R<LoginUserCapitalVO> capital = capitalAccountService.getUserCapital();
			R<LoginUserFuelVO> fuel = fuelAccountService.getUserFuel();
			R<AppCurrencyVO> tronCurrency = currencyService.getAppCurrency(WalletConstant.USDT,UserEnums.Chain.TRON.getValue());
			R<AppCurrencyVO> bscCurrency = currencyService.getAppCurrency(WalletConstant.USDT,UserEnums.Chain.BSC.getValue());
			UserBalanceVO vo = new UserBalanceVO();
			vo.setCapital(capital.getData());
			vo.setFuel(fuel.getData());
			List<AppCurrencyVO> list = new ArrayList<>();
			list.add(tronCurrency.getData());
			list.add(bscCurrency.getData());
			vo.setCurrency(list);
			return R.ok(vo);
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 发送邮件
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<String> sendEmail(SendEmailDTO dto) {
		Map<String, String> textContentCode = new HashMap<>();
		// 确认提现
		if (dto.getType().equals(UserEnums.EmailType.Withdrawal_Request.getValue())) {
			if (dto.getWithdrawalEmail() == null) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"确认提现参数为空");
			}
			textContentCode.put("${actualWithdrawalAmount}",
					dto.getWithdrawalEmail().getActualWithdrawalAmount().setScale(6,RoundingMode.DOWN).stripTrailingZeros().toPlainString());
			textContentCode.put("${arrivalAddress}",dto.getWithdrawalEmail().getArrivalAddress());
		}
		return emailService.sendEmail(new User() {{
			setEmail(dto.getEmail());
		}}, UserEnums.EmailType.findType(dto.getType()),textContentCode);
	}

	/**
	 * 修改用户资金密码
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<String> updateUserPassword(UpdateUserPasswordDTO dto) {
		try {
			if (dto.getNewPassword() == null) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"新密码不能为空");
			}
			if (dto.getOldPassword() == null) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"旧密码不能为空");
			}
			PigxUser user = SecurityUtil.getLoginUser();
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			// 校验验证码
			String key = user.getEmail() + " massage = " + RedisMessageType.Customer_Modify_MONEY_PASSWORD;
			if (Boolean.FALSE.equals(stringRedisTemplate.hasKey(key))) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码已过期");
			}
			String code = stringRedisTemplate.opsForValue().get(key);
			if (code == null || !code.equals(dto.getVerificationCode())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码错误");
			}
			User select = baseMapper.selectById(user.getId());
			if (select == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			if (!dto.getOldPassword().equals(select.getPassword())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNSUPPORTED_OPERATION.getCode(),"旧密码错误");
			}
			baseMapper.update(new User(){{
				setPassword(dto.getNewPassword());
			}},new QueryWrapper<User>(){{
				eq("id",select.getId());
			}});
			stringRedisTemplate.delete(key);
			return R.ok("修改密码成功");
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}

	}

	/**
	 * 修改用户邮箱
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<String> updateUserEmail(UpdateUserEmailDTO dto) {
		try {
			if (dto.getNewEmail() == null) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"新邮箱不能为空");
			}
			PigxUser user = SecurityUtil.getLoginUser();
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			// 校验验证码
			String key = dto.getNewEmail() + " massage = " + RedisMessageType.Customer_Modify_Email;
			if (Boolean.FALSE.equals(stringRedisTemplate.hasKey(key))) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码已过期");
			}
			String code = stringRedisTemplate.opsForValue().get(key);
			if (code == null || !code.equals(dto.getVerificationCode())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码错误");
			}
			baseMapper.update(new User(){{
				setEmail(dto.getNewEmail());
			}},new QueryWrapper<User>(){{
				eq("id",user.getId());
			}});
			stringRedisTemplate.delete(key);
			return R.ok("修改邮箱成功");
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 修改地址
	 * @return
	 */
	@Override
	public R<String> updateLoginAddress(HttpHeaders header,UpdateLoginAddressDTO dto) {
		try {
			// 获取当前登录用户
			PigxUser pigxUser = SecurityUtil.getLoginUser();
			if (pigxUser == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			// 用户详情
			User user = baseMapper.selectById(pigxUser.getId());
			if (user == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
			}
			// 参数校验
			if (user.getEmail() == null || user.getEmail().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.UNSUPPORTED_OPERATION.getCode(),"当前用户未绑定邮箱");
			}
			if (dto.getAddress() == null || dto.getAddress().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"地址不能为空");
			}
			if (dto.getAddress().equals(user.getAddress())) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"地址无变化,无需修改");
			}
			Long count = baseMapper.selectCount(new QueryWrapper<User>() {{
				eq("address", dto.getAddress());
				ne("id", user.getId());
			}});
			if (count > 0) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"该地址已被注册");
			}
			if (dto.getPassword() == null || dto.getPassword().isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.MANDATORY_PARAM_EMPTY_OR_MALFORMED.getCode(),"资金密码不能为空");
			}
			if (!dto.getPassword().equals(user.getPassword())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN_ORDER_COMPOSITION.getCode(),"资金密码错误");
			}
			//获取加签客户massage，判断是否存在
			String messageKey = dto.getAddress() + " massage = " + RedisMessageType.UPDATE_LOGIN_ADDRESS_MESSAGE;
			String addressMessage = stringRedisTemplate.opsForValue()
					.get(messageKey);
			if (addressMessage == null || addressMessage.isEmpty()) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN_ORDER_COMPOSITION.getCode(),"请对地址进行加签");
			}
			// 校验邮箱验证码
			String emailKey = user.getEmail() + " massage = " + RedisMessageType.Customer_Modify_Address;
			if (Boolean.FALSE.equals(stringRedisTemplate.hasKey(emailKey))) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN_ORDER_COMPOSITION.getCode(),"验证码已过期");
			}
			String emailCode = stringRedisTemplate.opsForValue().get(emailKey);
			if (emailCode == null || !emailCode.equals(dto.getVerificationCode())) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN_ORDER_COMPOSITION.getCode(),"验证码错误");
			}
			// 修改
			baseMapper.updateById(new User(){{
				setId(user.getId());
				setAddress(dto.getAddress());
			}});
			// 获取当前用户token 强制登出
			Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
			OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
			String tokenValue = details.getTokenValue();
			tokenService.removeTokenById(tokenValue,SecurityConstants.FROM_IN);
			stringRedisTemplate.delete(messageKey);
			stringRedisTemplate.delete(emailKey);
			return R.ok("修改地址成功");
		} catch (DuckweedException e) {
			throw e;
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 用户注册绑定
	 * @param dto dto
	 * @return r
	 */
	@Override
	public R<String> registered(RegisteredUserDTO dto) {
		// 查询用户
		User user = baseMapper.selectOne(new QueryWrapper<User>() {{
			eq("id", dto.getUserId());
		}});
		if (user == null) {
			throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
		}
		Long count = baseMapper.selectCount(new QueryWrapper<User>() {{
			eq("email", dto.getEmail());
		}});
		if (count > 0) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"该邮箱已被注册过");
		}
		// 校验验证码
		/*String key = dto.getEmail() + " massage = " + RedisMessageType.Customer_Registration;
		Boolean hasKey = stringRedisTemplate.hasKey(key);
		if (Boolean.FALSE.equals(hasKey)) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码已过期");
		}
		String s = stringRedisTemplate.opsForValue().get(key);
		if (s == null || !s.equals(dto.getVerificationCode())) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"验证码错误");
		}*/
		// 设置邮箱 用户名 资金密码
		user.setEmail(dto.getEmail());
		user.setUserName(dto.getUserName());
		user.setPassword(dto.getPassword());
		// 初始化等级状态等基础信息
		user.setLevel(UserEnums.Level.LEVEL_0.getValue());
		user.setIsActivation(CommonDictEnum.YesOrNo.NO.getValue());
		user.setIsDisableLevel(CommonDictEnum.YesOrNo.NO.getValue());
		// 随机uuid邀请码
		UUID id = UUID.randomUUID();
		String[] idd = id.toString().split("-");
		user.setInvitationCode(idd[0] + idd[1]);
		// 查询用户邀请码对应上级信息
		if (dto.getInvitationCode() != null && !dto.getInvitationCode().isEmpty()) {
			Long parent = updateParentByRegistered(dto.getInvitationCode());
			user.setParentId(parent);
		}
		try {
			mysqlUtil.startLocalTx();
			baseMapper.updateById(user);
			// 新增USC地址
			addressService.insertByRegistered(user);
			// 新增资金账户
			capitalAccountService.createCapital(user);
			// 新增燃料账户
			fuelAccountService.createFuel(user);
			mysqlUtil.commitLocalTx();
			// stringRedisTemplate.delete(key);
			return R.ok("注册成功");
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public R<String> adminInsert(User user) {
		user.setId(idWorker.nextId());
		// 随机uuid邀请码
		UUID id = UUID.randomUUID();
		String[] idd = id.toString().split("-");
		user.setInvitationCode(idd[0] + idd[1]);
		Long email = baseMapper.selectCount(new QueryWrapper<User>() {{
			eq("email", user.getEmail());
		}});
		if (email > 0) {
			throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"该邮箱已被注册过");
		}
		try {
			mysqlUtil.startLocalTx();
			baseMapper.insert(user);
			// 新增USC地址
			addressService.insertByRegistered(user);
			// 新增资金账户
			capitalAccountService.createCapital(user);
			// 新增燃料账户
			fuelAccountService.createFuel(user);
			mysqlUtil.commitLocalTx();
			return R.ok("添加用户成功");
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	/**
	 * 用户注册时更新所有关系上级
	 * @param invitationCode 邀请码
	 * @return parent_id
	 */
	public Long updateParentByRegistered(String invitationCode) {
		User one = baseMapper.selectOne(new QueryWrapper<User>() {{
			eq("invitation_code", invitationCode);
		}});
		if (one == null) {
			return null;
			// throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN.getCode(),"邀请码无效");
		}
		Long id = one.getParentId();
		// 获取所有父级链路
		List<User> list = new ArrayList<>();
		list.add(one);
		list.addAll(getAllParent(id));
		for (int i = 0; i < list.size(); i++) {
			try {
				User user = list.get(i);
				// 开启事务
				mysqlUtil.startLocalTx();
				// 社区人数统计 + 1
				user.setCommunityCount(user.getCommunityCount() + 1);
				// 直推人数 + 1
				if (i == 0) {
					user.setDirectInvitationCount(user.getDirectInvitationCount() + 1);
				}
				// 间推人数 + 1
				if (i == 1) {
					user.setIndirectInvitationCount(user.getIndirectInvitationCount() + 1);
				}
				baseMapper.updateById(user);
				// 提交事务
				mysqlUtil.commitLocalTx();
			} catch (Exception e) {
				// 回滚事务
				mysqlUtil.rollbackLocalTx();
			}
		}
		return one.getId();
	}

	/**
	 * 获取父级信息
	 * @param id 父级id
	 * @return user实体
	 */
	@Override
	public List<User> getAllParent(Long id) {
		try {
			List<User> list = new ArrayList<>();
			while (id != null) {
				try {
					User parent = baseMapper.selectById(id);
					if (parent == null) {
						id = null;
					} else {
						id = parent.getParentId();
						list.add(parent);
					}
				} catch (Exception e) {
					id = null;
				}
			}
			return list;
		} catch (Exception e) {
			return new ArrayList<>();
		}
	}

	/**
	 * 递归获取所有子集
	 * @param list list
	 * @param id 父级id
	 */
	public void getAllChild(List<User> list,Long id) {
		List<User> userList = baseMapper.selectList(new QueryWrapper<User>() {{
			eq("parent_id", id);
		}});
		if (userList.size() > 0) {
			list.addAll(userList);
			for (User user : userList) {
				getAllChild(list,user.getId());
			}
		}
	}

	/**
	 * 获取父子级关系树形数据
	 * @param user user
	 */
	public void getTreeChild(TreeUserVO user) {
		List<TreeUserVO> vos = baseMapper.selectChildByTree(user.getId());
		if (vos.size() > 0) {
			for (TreeUserVO vo : vos) {
				getTreeChild(vo);
			}
			user.setChild(vos);
		}
	}

	/**
	 * 获取父子级关系树形数据 - admin
	 * @param user user
	 */
	public void getTreeChild(AdminUserTreeVO user) {
		List<AdminUserTreeVO> vos = baseMapper.selectChildByAdminTree(user.getId());
		if (vos.size() > 0) {
			for (AdminUserTreeVO vo : vos) {
				getTreeChild(vo);
				vo.setLevel(UserEnums.Level.findName(Integer.valueOf(vo.getLevel())));
				vo.setIsDisableLevel(CommonDictEnum.YesOrNo.findName(vo.getIsDisableLevel()));
			}
			user.setChild(vos);
		}
	}

	/**
	 * 用户下单后的相关操作
	 */
	@Override
	public void transactionThen(TransactionThenDTO dto) {
		try {
			mysqlUtil.startLocalTx();
			// 消耗燃料不可小于 0
			if (dto.getFuel() == null || dto.getFuel().compareTo(BigDecimal.ZERO) <= 0) {
				throw new DuckweedException(AbnormalEnum.MSG.UNKNOWN_ORDER_COMPOSITION.getCode(),"消耗燃料数量不可 <= 0");
			}
			// 燃油消耗记录
			FuelConsume consume = new FuelConsume();
			consume.setId(idWorker.nextId());
			consume.setUserId(dto.getUserId());
			consume.setFuelQuantity(dto.getFuel());
			consume.setType(dto.getFuelType().getValue());
			consume.setOrderId(dto.getOrderId());
			consume.setStrategyName(dto.getStrategyName());
			consume.setGrossProfit(dto.getGrossProfit());
			consume.setNetProfit(dto.getNetProfit());
			fuelConsumeService.save(consume);
			// 获取用户所有关系父级 (包括自身)
			List<User> parent = getAllParent(dto.getUserId());
			assert parent.size() > 0;
			// 社区总业绩更新
			for (User user : parent) {
				baseMapper.userAchievementQuantityCheck(user.getId(),dto.getFuel());
			}
			mysqlUtil.commitLocalTx();
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
		}
	}

	/**
	 * 制度分成
	 *
	 * @param userId     充值用户id
	 * @param quantity   充值数量
	 * @param transferId
	 */
	@Async
	@Override
	public void distribution(Long userId , BigDecimal quantity, Long transferId) {
		try {
			mysqlUtil.startLocalTx();
			// 先处理固定配比
			List<FuelReceiveDividends> list = new ArrayList<>();
			// 平台纯收入比例 初始40% 如有其他任何未进行分配的 全部纳入平台纯收入
			BigDecimal platformProfit = FuelProfitConstant.PLATFORM_PROFIT;
			// 平台保险金
			list.add(new FuelReceiveDividends(){{
				setId(idWorker.nextId());
				setFuelConsumeId(transferId);
				setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
				setType(FuelReceiveDividendsEnums.Type.MARGIN.getValue());
				setFuelQuantity(quantity.multiply(FuelProfitConstant.MARGIN));
				setFuelProportion(FuelProfitConstant.MARGIN);
			}});
			// 查询是否有合伙人
			List<User> userList = new User().selectList(new QueryWrapper<User>() {{
				eq("level", UserEnums.Level.LEVEL_2.getValue());
			}});
			if (userList.size() > 0) {
				// 分配总额度
				BigDecimal multiply = quantity.multiply(FuelProfitConstant.LevelProfit.LEVEL_2.getProfit());
				// 每个合伙人能分配到的额度
				int a = 0;
				for (User user : userList) {
					long data = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
						eq("type", TransferEnums.Type.TO_FUEL.getValue());
						eq("user_id", user.getId());
					}});
					if (data > 0) {
						a += 1;
					}
				}
				BigDecimal divide = multiply.divide(BigDecimal.valueOf(a),8, RoundingMode.DOWN);
				BigDecimal profit = FuelProfitConstant.LevelProfit.LEVEL_2.getProfit()
						.divide(BigDecimal.valueOf(a),8, RoundingMode.DOWN);
				// 遍历用户,将这部分金额平均分配
				int count = 0;
				for (User user : userList) {
					long data = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
						eq("type", TransferEnums.Type.TO_FUEL.getValue());
						eq("user_id", user.getId());
					}});
					if (data == 0) {
						continue;
					}
					list.add(new FuelReceiveDividends(){{
						setId(idWorker.nextId());
						setFuelConsumeId(transferId);
						setUserId(user.getId());
						setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
						setType(FuelReceiveDividendsEnums.Type.LEVEL_2.getValue());
						setFuelQuantity(divide);
						setFuelProportion(profit);
					}});
					count += 1;
				}
				if (count == 0) {
					platformProfit = platformProfit.add(FuelProfitConstant.LevelProfit.LEVEL_2.getProfit());
				}
			} else {
				platformProfit = platformProfit.add(FuelProfitConstant.LevelProfit.LEVEL_2.getProfit());
			}
			// 获取所有父级
			List<User> parent = getAllParent(userId);
			// 如果链路中没有社区 则直接把社区奖励归入平台纯收入
			int size = (int) parent.stream().filter(e ->
					e.getLevel().equals(UserEnums.Level.LEVEL_1.getValue()) || e.getLevel().equals(UserEnums.Level.LEVEL_2.getValue())
			).count();
			if (size > 0) {
				List<User> level1List = new ArrayList<>();
				for (User user : parent) {
					if (user.getLevel().equals(UserEnums.Level.LEVEL_1.getValue()) || user.getLevel().equals(UserEnums.Level.LEVEL_2.getValue())) {
						level1List.add(user);
						if (level1List.size() == 2) {
							break;
						}
					}
				}
				// 链路只有一个社区 获取全额奖励
				if (level1List.size() == 1) {
					User user = level1List.get(0);
					long data = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
						eq("type", TransferEnums.Type.TO_FUEL.getValue());
						eq("user_id", user.getId());
					}});
					if (data > 0) {
						BigDecimal decimal = quantity.multiply(FuelProfitConstant.LevelProfit.LEVEL_1.getProfit());
						list.add(new FuelReceiveDividends(){{
							setId(idWorker.nextId());
							setFuelConsumeId(transferId);
							setUserId(user.getId());
							setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
							setType(FuelReceiveDividendsEnums.Type.LEVEL_1.getValue());
							setFuelQuantity(decimal);
							setFuelProportion(FuelProfitConstant.LevelProfit.LEVEL_1.getProfit());
						}});
					} else {
						platformProfit = platformProfit.add(FuelProfitConstant.LevelProfit.LEVEL_1.getProfit());
					}
				}
				// 社区触发平级
				if (level1List.size() == 2) {
					// 被平级的10%
					User user1 = level1List.get(0);
					long data = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
						eq("type", TransferEnums.Type.TO_FUEL.getValue());
						eq("user_id", user1.getId());
					}});
					if (data > 0) {
						BigDecimal decimal = quantity.multiply(new BigDecimal("0.1"));
						list.add(new FuelReceiveDividends(){{
							setId(idWorker.nextId());
							setFuelConsumeId(transferId);
							setUserId(user1.getId());
							setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
							setType(FuelReceiveDividendsEnums.Type.EQUALITY.getValue());
							setFuelQuantity(decimal);
							setFuelProportion(new BigDecimal("0.1"));
						}});
					} else {
						platformProfit = platformProfit.add(new BigDecimal("0.1"));
					}
					// 触发平级的5%
					User user2 = level1List.get(1);
					long data2 = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
						eq("type", TransferEnums.Type.TO_FUEL.getValue());
						eq("user_id", user2.getId());
					}});
					if (data2 > 0) {
						BigDecimal decimal2 = quantity.multiply(new BigDecimal("0.05"));
						list.add(new FuelReceiveDividends(){{
							setId(idWorker.nextId());
							setFuelConsumeId(transferId);
							setUserId(user2.getId());
							setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
							setType(FuelReceiveDividendsEnums.Type.EQUALITY.getValue());
							setFuelQuantity(decimal2);
							setFuelProportion(new BigDecimal("0.05"));
						}});
					} else {
						platformProfit = platformProfit.add(new BigDecimal("0.05"));
					}
				}
			} else {
				platformProfit = platformProfit.add(FuelProfitConstant.LevelProfit.LEVEL_1.getProfit());
			}
			// 间推
			if (parent.size() > 2) {
				BigDecimal decimal = quantity.multiply(FuelProfitConstant.INDIRECT);
				User user = parent.get(2);
				long data = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
					eq("type", TransferEnums.Type.TO_FUEL.getValue());
					eq("user_id", user.getId());
				}});
				if (data > 0) {
					list.add(new FuelReceiveDividends(){{
						setId(idWorker.nextId());
						setFuelConsumeId(transferId);
						setUserId(user.getId());
						setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
						setType(FuelReceiveDividendsEnums.Type.INDIRECT.getValue());
						setFuelQuantity(decimal);
						setFuelProportion(FuelProfitConstant.INDIRECT);
					}});
				} else {
					platformProfit = platformProfit.add(FuelProfitConstant.INDIRECT);
				}
			} else {
				platformProfit = platformProfit.add(FuelProfitConstant.INDIRECT);
			}
			// 直推
			if (parent.size() > 1) {
				BigDecimal decimal = quantity.multiply(FuelProfitConstant.DIRECT);
				User user = parent.get(1);
				long data = new TransferDetailed().selectCount(new QueryWrapper<TransferDetailed>() {{
					eq("type", TransferEnums.Type.TO_FUEL.getValue());
					eq("user_id", user.getId());
				}});
				if (data > 0) {
					list.add(new FuelReceiveDividends(){{
						setId(idWorker.nextId());
						setFuelConsumeId(transferId);
						setUserId(user.getId());
						setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
						setType(FuelReceiveDividendsEnums.Type.DIRECT.getValue());
						setFuelQuantity(decimal);
						setFuelProportion(FuelProfitConstant.DIRECT);
					}});
				} else {
					platformProfit = platformProfit.add(FuelProfitConstant.DIRECT);
				}
			} else {
				platformProfit = platformProfit.add(FuelProfitConstant.DIRECT);
			}
			// 平台纯收入统计
			BigDecimal finalPlatformProfit = platformProfit;
			list.add(new FuelReceiveDividends(){{
				setId(idWorker.nextId());
				setFuelConsumeId(transferId);
				setIsSuccess(CommonDictEnum.YesOrNo.NO.getValue());
				setType(FuelReceiveDividendsEnums.Type.NET_INCOME.getValue());
				setFuelQuantity(quantity.multiply(finalPlatformProfit));
				setFuelProportion(finalPlatformProfit);
			}});
			fuelReceiveDividendsService.addList(list);
			mysqlUtil.commitLocalTx();
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
		}
	}

	/**
	 * 获取直推
	 * @param id id
	 * @return r
	 */
	public List<SelectUserByIdListVO> getDirectUser(Long id) {
		try {
			List<User> list = baseMapper.selectList(new QueryWrapper<User>() {{
				eq("parent_id", id);
			}});
			List<Long> longs = list.stream().map(User::getId).collect(Collectors.toList());
			return baseMapper.selectByIdList(longs);
		} catch (Exception e) {
			return new ArrayList<>();
		}
	}

	/**
	 * 获取间推
	 * @param id id
	 * @return r
	 */
	public List<SelectUserByIdListVO> getIndirectUser(Long id) {
		try {
			List<User> list = baseMapper.selectList(new QueryWrapper<User>() {{
				eq("parent_id", id);
			}});
			List<Long> longs = list.stream().map(User::getId).collect(Collectors.toList());
			List<User> users = baseMapper.selectList(new QueryWrapper<User>() {{
				in("parent_id", longs);
			}});
			List<Long> longList = users.stream().map(User::getId).collect(Collectors.toList());
			return baseMapper.selectByIdList(longList);
		} catch (Exception e) {
			return new ArrayList<>();
		}
	}

	/**
	 * 获取所有子集
	 * @param id id
	 * @return r
	 */
	public List<SelectUserByIdListVO> getAllChildUser(Long id) {
		try {
			// 伞下节点查询
			List<User> userList = new ArrayList<>();
			getAllChild(userList,id);
			// 筛选id 开始查询
			List<Long> list = userList.stream().map(User::getId).collect(Collectors.toList());
			return baseMapper.selectByIdList(list);
		} catch (Exception e) {
			return new ArrayList<>();
		}
	}

	@Override
	public R<List<SelectUserByIdListVO>> getChildVoList(Integer type,Long userId) {
		try {
			List<SelectUserByIdListVO> listVOS = new ArrayList<>();
			// 获取直推
			if (type == 0) {
				listVOS = getDirectUser(userId);
			}
			// 获取间推
			if (type == 1) {
				listVOS = getIndirectUser(userId);
			}
			// 获取所有子集
			if (type == 2) {
				listVOS = getAllChildUser(userId);
			}
			listVOS = listVOS.stream()
					.sorted(Comparator.comparing(SelectUserByIdListVO::getCommunityCount).reversed())
					.collect(Collectors.toList());
			for (SelectUserByIdListVO u : listVOS) {
				// 字典项翻译
				u.setLevel(UserEnums.Level.findName(Integer.valueOf(u.getLevel())));
				if (u.getFuelQuantity() != null) {
					u.setFuelQuantity(u.getFuelQuantity().setScale(3,RoundingMode.DOWN).stripTrailingZeros());
				}
				if (u.getRechargeQuantity() != null) {
					u.setRechargeQuantity(u.getRechargeQuantity().setScale(3,RoundingMode.DOWN).stripTrailingZeros());
				}
				if (u.getFuelBalance() != null) {
					u.setFuelBalance(u.getFuelBalance().setScale(3,RoundingMode.DOWN).stripTrailingZeros());
				}
			}
			return R.ok(listVOS);
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}


	/**
	 * TODO 获取后台首页数据统计
	 * @return TODO
	 */
	public R dataStatistics() {
		// 统计充值
		List<RechargeRecord> list = new RechargeRecord().selectList(new QueryWrapper<RechargeRecord>() {{
			select("sum(quantity) 'quantity',date_format( create_time, '%Y-%m-%d' ) 'createTime'");
			groupBy("date_format( create_time, '%Y-%m-%d' ) 'createTime'");
			eq("type", RechargeRecordEnum.Type.CHAIN_RECHARGE.getValue());
			eq("state", RechargeRecordEnum.Status.SUCCESS.getValue());
		}});
		return R.ok();
	}

}
